/*!
* @file Placement.h
* @brief 三维定位
* @date 2024/9/12
*/
#pragma once

#include "Vector3D.h"
#include "Rotation.h"

namespace data
{
class Matrix4d;

/*!
* @brief 三维定位
*/
class DATA_API Placement
{
public:
    Vector3d position;
    Rotation rotation;

    /*!
    * @brief 定位构造
    */
    Placement() = default;
    Placement(const Placement&) = default;
    Placement(Placement&&) = default;
    Placement(const Vector3d& pos, const Rotation& rot);
    Placement(const Vector3d& pos, const Rotation& rot, const Vector3d& cnt);
    ~Placement() = default;

    void Set(const Vector3d& pos, const Rotation& rot);
    void Move(const Vector3d& vector);

    /*!
    * @brief 定位运算
    */
    Placement& operator=(const Placement&) = default;
    Placement& operator=(Placement&&) = default;
    Placement operator*(const Placement& p) const;
    Placement& operator*=(const Placement& p);
    bool operator==(const Placement& p) const;
    bool operator!=(const Placement& p) const;

    Placement& MultRight(const Placement& p);
    Placement& MultLeft(const Placement& p);
    Vector3d MultVec(const Vector3d& src) const;

    void Invert();
    Placement Inverse() const;

    bool IsIdentity() const;
    bool IsEqual(const Placement&, double tol) const;
    bool IsIdentity(double tol) const;

    Matrix4d ToMatrix() const;
};

inline Vector3d operator*(const Vector3d& vec, const Placement& p)
{
    return p.MultVec(vec);
}

inline Vector3d& operator*=(Vector3d& vec, const Placement& p)
{
    vec = p.MultVec(vec);
    return vec;
}

/*!
* @brief 文本信息输出
*/
inline std::ostream& operator<< (std::ostream& stream, const Placement& p)
{
    return stream << "{ position: " << p.position << ", rotation: " << p.rotation << " }";
}
}  // namespace data
